package com.mm.domain.wechat;

import cn.hutool.core.util.StrUtil;
import com.mm.base.constant.MiniConstants;
import com.mm.util.common.CreateOrderUtil;
import com.mm.util.common.CommonUtils;
import com.mm.util.wechat.IWXPayDomain;
import com.mm.util.wechat.WXPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * 描述: 微信小程序支付-实体
 *
 * @author: yanglin
 * @Date: 2021-08-25-9:53
 * @Version: 1.0
 */
@Slf4j
public class MiniPayInfo extends WXPayConfig {

    public static MiniPayInfo getInstance(){
        return new MiniPayInfo();
    }

    /**
     * 随机字符串
     *
     * @return
     */
    public String getNonceStr() {
        return DigestUtils.md5Hex(WXPayUtil.generateNonceStr());
    }

    /**
     * 商品描述
     *
     * @param body
     * @return
     */
    public String getBody(String body) {
        if (StrUtil.isNotBlank(body)) {
            return body;
        }
        return "商品描述";
    }

    /**
     * 设备号
     * 自定义参数，可以为终端设备号(门店号或收银设备ID)，PC网页或公众号内支付可以传"WEB"
     * N
     * @return
     */
    public String getDeviceInfo(){
        return MiniConstants.APP_DEVICE_INFO;
    }

    /**
     * 商户订单号
     *
     * @param orderCode
     * @return
     */
    public String getOutTradeNo(String orderCode) {
        if (StrUtil.isNotBlank(orderCode)) {
            return orderCode;
        }
        return CreateOrderUtil.generateOrderNo("WX-");
    }

    /**
     * 商户退款单号
     * @return
     */
    public String getOutRefundNo() {
        return CreateOrderUtil.generateOrderNo("TK-");
    }

    /**
     * 标价(订单)金额,标价为分
     *
     * @param totalFee
     * @return
     */
    public String getTotalFee(Integer totalFee) {
        return StrUtil.toString(totalFee);
    }

    /**
     * 退款金额
     * @param refundFee
     * @return
     */
    public String getRefundFee(Integer refundFee) {
        return StrUtil.toString(refundFee);
    }



    /**
     * 终端IP
     *
     * @param request
     * @return
     */
    public String getSpbillCreateIp(HttpServletRequest request) {
        return CommonUtils.getRemortIP(request);
    }

    /**
     * 通知地址/回调地址
     *
     * @return
     */
    public String getNotifyUrl() {
        return MiniConstants.APP_NOTIFY_URL;
    }

    /**
     * 交易类型-小程序(JSAPI)
     *
     * @return
     */
    public String getTradeType() {
        return MiniConstants.APP_TRADE_TYPE;
    }

    /**
     * 签名
     *
     * @param sortedMap
     * @return
     * @throws Exception
     */
    public String getSign(SortedMap sortedMap) throws Exception {
        String sign = WXPayUtil.generateSignature(sortedMap, MiniConstants.APP_KEY);
        sortedMap.put("sign", sign);
        if (WXPayUtil.isSignatureValid(sortedMap, MiniConstants.APP_KEY)) {
            return sign;
        }
        return WXPayUtil.generateSignature(sortedMap, MiniConstants.APP_KEY);
    }

    /**
     * 签名类型，默认为MD5，支持HMAC-SHA256和MD5。
     *
     * @return
     */
    public String getSignType() {
        return MiniConstants.APP_SIGN_TYPE;
    }

    /**
     * 用户openId
     *
     * @param openId
     * @return
     */
    public String getOpenId(String openId) {
        return openId;
    }

    /**
     * 小程序ID
     *
     * @return
     */
    @Override
    public String getAppID() {
        return MiniConstants.APP_ID;
    }

    /**
     * 商户号
     *
     * @return
     */
    @Override
    public String getMchID() {
        return MiniConstants.APP_MCH_ID;
    }

    /**
     * API 密钥
     *
     * @return
     */
    @Override
    public String getKey() {
        return MiniConstants.APP_KEY;
    }

    /**
     * 获取商户证书内容
     *
     * @return
     */
    @Override
    public InputStream getCertStream() {
        return null;
    }

    /**
     * 获取WXPayDomain, 用于多域名容灾自动切换
     *
     * @return
     */
    @Override
    public IWXPayDomain getWXPayDomain() {
        return null;
    }

    /**
     * 生成下单请求参数
     *
     * @param req
     * @param body
     * @param orderCode
     * @param totalFree
     * @param openId
     * @return
     */
    public String bulidPlaceOrderParams(HttpServletRequest req, String body, String orderCode, Integer totalFree, String openId) throws Exception {
        SortedMap<String, String> params = new TreeMap<String, String>();
        // 小程序ID
        params.put("appid", getAppID());
        // 商户号
        params.put("mch_id", getMchID());
        // 随机字符串
        params.put("nonce_str", getNonceStr());
        // 商品描述
        params.put("body", getBody(body));
        // 商户订单号
        params.put("out_trade_no", getOutTradeNo(orderCode));
        // 标价金额,标价为分
        params.put("total_fee", getTotalFee(totalFree));
        // 终端IP
        params.put("spbill_create_ip", getSpbillCreateIp(req));
        // 通知地址
        params.put("notify_url", getNotifyUrl());
        // 交易类型
        params.put("trade_type", getTradeType());
        // 用户openid
        params.put("openid", getOpenId(openId));
        // 3.0 生成自己的签名
        params.put("sign", getSign(params));
        return WXPayUtil.mapToXml(params);
    }


    /**
     * 生成查询订单/关闭订单/查询退款金额参数
     *
     * @param orderCode
     * @return
     * @throws Exception
     */
    public String bulidQueryOrCloseOrderParams(String orderCode) throws Exception {
        SortedMap<String, String> params = new TreeMap<String, String>();
        // 小程序ID
        params.put("appid", getAppID());
        // 商户号
        params.put("mch_id", getMchID());
        // 随机字符串
        params.put("nonce_str", getNonceStr());
        // 商户订单号
        params.put("out_trade_no", getOutTradeNo(orderCode));
        // 3.0 生成自己的签名
        params.put("sign", getSign(params));
        return WXPayUtil.mapToXml(params);
    }

    /**
     * 生成申请退款参数
     * @param orderCode
     * @param totalFree
     * @param refundFree
     * @return
     * @throws Exception
     */
    public String bulidRefundParams(String orderCode, Integer totalFree, Integer refundFree) throws Exception {
        SortedMap<String, String> params = new TreeMap<String, String>();
        // 小程序ID
        params.put("appid", getAppID());
        // 商户号
        params.put("mch_id", getMchID());
        // 随机字符串
        params.put("nonce_str", getNonceStr());
        // 商户订单号
        params.put("out_trade_no", getOutTradeNo(orderCode));
        // 商户退款单号
        params.put("out_refund_no", getOutRefundNo());
        // 订单金额
        params.put("total_fee", getTotalFee(totalFree));
        // 退款金额
        params.put("refund_fee", getRefundFee(refundFree));
        // 通知地址
        params.put("notify_url", getNotifyUrl());
        // 3.0 生成自己的签名
        params.put("sign", getSign(params));
        return WXPayUtil.mapToXml(params);
    }
}
